package nba2kmodtool.filedesc;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.List;

import nba2kmodtool.util.ByteFileReader;

/**
 * NBA2K Game Model Exporter
 * @company ZSword (C) Copyright
 * @author JemiZhuu(周士淳)
 * @category N2kModelExporter
 * @version 1.0
 * @since 2011-11-16
 */
public class N2kModelExporter {
	private static final boolean IS_DEBUG = BaseIffFile.IS_DEBUG;

	protected BaseIffFile iff;
	protected File file;

	protected N2kModelExporter(BaseIffFile iff) {
		this.iff = iff;
		this.file = iff.file;
	}

	public void exportModelFile(File outfile, N2k3DModelPart[] models) throws IOException {
		ByteFileReader in = new ByteFileReader(file, "r");
		ByteFileReader out = new ByteFileReader(outfile, "rw");
		out.write("2KM".getBytes());
		out.write(0x00);
		int num = models.length;
		out.writeInt(Integer.reverseBytes(num));
		out.writeInt(Integer.reverseBytes(20));
		int partNum = 0;
		for (int i = 0; i < num; i++) {
			N2k3DModelPart part = models[i];
			if (part == null || part.childNum < 1) {
				continue;
			}
			List<FloatBuffer> vertexs = iff.getChildModelVertets(part, in);
			List<IntBuffer> faces = iff.resolve3DModelFaceData(part, in);
			for (int j = 0; j < part.childNum; j++) {
				partNum++;
				String partName = String.format("%d-%d", part.no, j);
				out.write(partName.getBytes());
				for (int n = 0; n < 8 - partName.length(); n++) {
					out.write(0x00);
				}
				FloatBuffer vertBuf = vertexs.get(j * 2);
				FloatBuffer uvnBuf = vertexs.get(j * 2 + 1);
				IntBuffer fcBuf = faces.get(j);
				int vertNum = vertBuf.array().length / 3;
				int faceNum = fcBuf.array().length / 3;
				out.writeInt(Integer.reverseBytes(vertNum));
				for (int n = 0; n < vertNum; n++) {
					//write vertex position
					out.writeIntBigEndin(Float.floatToIntBits(vertBuf.get()));
					out.writeIntBigEndin(Float.floatToIntBits(vertBuf.get()));
					out.writeIntBigEndin(Float.floatToIntBits(vertBuf.get()));
					//write uv position
					out.writeIntBigEndin(Float.floatToIntBits(uvnBuf.get()));
					out.writeIntBigEndin(Float.floatToIntBits(uvnBuf.get()));
				}
				out.writeInt(Integer.reverseBytes(faceNum));
				for (int n = 0; n < faceNum; n++) {
					out.writeShortBigEndin(fcBuf.get());
					out.writeShortBigEndin(fcBuf.get());
					out.writeShortBigEndin(fcBuf.get());
				}
			}
		}
		long len = out.getFilePointer();
		//fix part num
		out.seek(0x04);
		out.writeInt(Integer.reverseBytes(partNum));
		out.setLength(len);
		in.close();
		out.close();
	}

	public void exportModelFile0(File outfile, N2k3DModelPart[] models) throws IOException {
		ByteFileReader in = new ByteFileReader(file, "r");
		ByteFileReader out = new ByteFileReader(outfile, "rw");
		out.write("2KM".getBytes());
		out.write(0x00);
		int num = models.length;
		out.writeInt(Integer.reverseBytes(num));
		for (int i = 0; i < num; i++) {
			N2k3DModelPart part = models[i];
			String partName = String.format("%-3d", part.no);
			out.write(partName.getBytes());
			out.write(0x00);
			//write vertex datas
			in.seek(part.vertexDataStart);
			int vertexNum = part.vertexNum;
			int perSize = part.perVertexSize;
			out.writeInt(Integer.reverseBytes(vertexNum));
			out.writeInt(Integer.reverseBytes(12));
			ByteBuffer buffer = ByteBuffer.allocate(vertexNum * 12);
			for (int j = 0; j < vertexNum; j++) {
				byte[] buff = new byte[12];
				in.read(buff);
				buffer.put(buff);
				in.skipBytes(perSize - 12);
			}
			out.write(buffer.array());
			//write face datas
			ByteBuffer datas = ByteBuffer.allocate(part.faceDataSize * 2);
			in.seek(part.faceDataStart);
			in.read(datas.array());
			IntBuffer faces = N2kModelPartReader.decompressModelFaceDatas(datas);
			faces.rewind();
			out.writeInt(Integer.reverseBytes(faces.capacity() / 3));
			for (int j = 0; j < faces.capacity(); j++) {
				out.writeShortBigEndin(faces.get());
			}
		}
		out.setLength(out.getFilePointer());
		in.close();
		out.close();
	}

}
